<?php
// 应用公共文件

use app\common\util\Snowflake;
use think\facade\Cache;

if (!function_exists('get_tree')) {
    /**
     * 递归获取树形
     *
     * @param array $data
     * @param int $parent_id
     * @param string $parent_key
     * @param string $child_key
     * @param int|null $max_level
     * @param int $current_level
     * @return array
     */
    function get_tree(
        array $data,
        int $parent_id = 0,
        string $parent_key = 'pid',
        string $child_key = 'id',
        ?int $max_level = null,
        int $current_level = 1
    ): array {
        $tree = [];
        foreach ($data as $item) {
            if ($item[$parent_key] == $parent_id) {
                // 递归终止条件：达到最大层级时不再生成子级
                if ($max_level !== null && $current_level >= $max_level) {
                    $item['children'] = [];
                } else {
                    $item['children'] = get_tree(
                        $data,
                        $item[$child_key],
                        $parent_key,
                        $child_key,
                        $max_level,
                        $current_level + 1
                    );
                }
                $tree[] = $item;
            }
        }
        return $tree;
    }
}


if (!function_exists('build_tree')) {
    /**
     * 生成路由菜单
     *
     * @param array $array
     * @param string $pid
     * @param string $childKey
     * @param string $buttonKey
     * @return array
     */
    function build_tree(array $array, string $pid = 'pid', string $childKey = 'children', string $buttonKey = 'buttons'): array
    {
        // 如果输入数组为空，直接返回空数组
        if (empty($array)) {
            return [];
        }

        // 创建一个ID到节点的引用映射
        $map = [];
        foreach ($array as &$node) {
            $map[$node['id']] = &$node;
            // 初始化children数组为空数组（不需要再次引用，因为$item已经是引用）
            $map[$node['id']][$childKey] = [];
            $map[$node['id']][$buttonKey] = [];
        }
        // 构建树形结构
        $rootNodes = [];
        foreach ($array as $item) {
            // 获取父节点的引用（如果存在）
            $parentId = $item[$pid] ?? null; // 使用null合并运算符处理未定义的$pid键

            if ($parentId === null || $parentId === 0 || isset($map[$parentId])) {
                if (isset($map[$parentId])) {
                    $parent = &$map[$parentId];
                    // 将当前节点添加到父节点的children数组中
                    $parent[$childKey][] = &$map[$item['id']];
                    if ($item['type'] === 1) {
                        $parent[$buttonKey][] = &$map[$item['id']]; // 放入buttons数组
                    }
                } else {
                    // 仅当 parentId 为 null 或 0 时作为根节点
                    $rootNodes[] = &$map[$item['id']];
                }
            }
        }
        return $rootNodes;
    }
}

if (!function_exists('html_purify')) {
    /**
     * 过滤HTML内容，防止XSS攻击内容
     *
     * @param $dirtyHtml
     * @param string $configName
     * @return string
     */
    function html_purify($dirtyHtml, string $configName = 'default'): string
    {
        static $purifiers = [];

        if (!isset($purifiers[$configName])) {
            $config = HTMLPurifier_Config::createDefault();
            foreach (config("htmlpurifier.{$configName}") as $key => $value) {
                $config->set($key, $value);
            }
            $purifiers[$configName] = new HTMLPurifier($config);
        }

        return $purifiers[$configName]->purify($dirtyHtml);
    }
}

if(!function_exists('filter_sensitive_words')) {
    /**
     * 敏感词过滤
     *
     * @param string $text 发送内容
     * @param array $sensitiveWords 敏感词库
     * @return string
     */
    function filter_sensitive_words(string $text, array $sensitiveWords = []): string
    {
        if (empty($sensitiveWords)) {
            // 系统自定义敏感词
            $words = get_config('sensitive_words_config.sensitive_words');
            $sensitiveWords = explode(',', $words);
        }

        // 转义敏感词并构建正则模式
        $escapedWords = array_map(function ($word) {
            return preg_quote($word, '/');
        }, $sensitiveWords);

        // 匹配完整单词（支持Unicode字符）
        $pattern = '/(?<!\p{L})(' . implode('|', $escapedWords) . ')(?!\p{L})/iu';

        // 替换为等长星号
        return preg_replace_callback(
            $pattern,
            function ($matches) {
                return str_repeat('*', mb_strlen($matches[0]));
            },
            $text
        );
    }
}

if(!function_exists('get_config')) {
    /**
     * 获取配置
     *
     * @param string $identifier 格式 分组标识 或 分组标识.配置key
     * @return mixed
     */
    function get_config(string $identifier): mixed
    {
        $service = app()->make(\app\common\service\system\SysConfigService::class);
        return $service->getConfig($identifier);
    }
}

if(!function_exists('get_id')) {
    /**
     * 雪花唯一ID
     *
     * @return int
     */
    function get_id(): int
    {
        $snowflake = new Snowflake(1, \think\facade\Cache::store('redis')->handler());
        return $snowflake->getId();
    }
}

if(!function_exists('convertUtcToTimezone')) {
    /**
     * 将UTC时间转换为目标时区的时间
     *
     * @param string $dateTimeStr ISO 8601 格式的时间字符串
     * @param string $targetTimezone 目标时区，例如 'Asia/Shanghai'
     * @param string $outputFormat 输出的时间格式，默认为 'Y-m-d H:i:s'
     * @return string 转换后的时间字符串
     */
    function convertUtcToTimezone(string $dateTimeStr, string $targetTimezone = 'Asia/Shanghai', string $outputFormat = 'Y-m-d'): string
    {
        try {
            // 创建 DateTime 对象并设置为 UTC 时间
            $dateTime = new \DateTime($dateTimeStr, new \DateTimeZone('UTC'));

            // 转换为目标时区
            $dateTime->setTimezone(new \DateTimeZone($targetTimezone));

            // 返回格式化后的时间字符串
            return $dateTime->format($outputFormat);
        } catch (\Exception $e) {
            // 处理可能发生的异常
            error_log("日期转换失败: " . $e->getMessage());
            return ''; // 或者根据需要返回其他值或抛出异常
        }
    }
}